package vip.lsjscl.flowboot.workflow.controller;

import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.redisson.api.RedissonClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;
import vip.lsjscl.flowboot.common.BusinessException;
import vip.lsjscl.flowboot.common.ResponseData;
import vip.lsjscl.flowboot.util.UserInfoHolder;
import vip.lsjscl.flowboot.util.constants.ActivityType;
import vip.lsjscl.flowboot.util.constants.TaskStatus;
import vip.lsjscl.flowboot.util.lock.DistributedLock;
import vip.lsjscl.flowboot.util.model.User;
import vip.lsjscl.flowboot.workflow.entity.DKActivity;
import vip.lsjscl.flowboot.workflow.entity.DKRuntimeTask;
import vip.lsjscl.flowboot.workflow.model.NodeData;
import vip.lsjscl.flowboot.workflow.model.dto.ProcessDataDto;
import vip.lsjscl.flowboot.workflow.repository.DKActivityRepository;
import vip.lsjscl.flowboot.workflow.repository.DKRuntimeTaskRepository;
import vip.lsjscl.flowboot.workflow.service.DKActivityService;
import vip.lsjscl.flowboot.workflow.service.DKRuntimeTaskService;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 任务管理控制器
 * 提供任务查询、处理、操作等功能
 *
 * @author zhangxingju
 * @date 2025/02/14
 */
@RestController
@RequestMapping("/api/workflow")
@RequiredArgsConstructor
public class DKTaskController {
    private static final Logger log = LoggerFactory.getLogger(DKTaskController.class);

    private final DKRuntimeTaskRepository runtimeTaskRepository;
    private final DKRuntimeTaskService taskService;
    private final DKActivityService activityService;
    private final DKActivityRepository activityRepository;
    private final UserInfoHolder userInfoHolder;
    private final RedissonClient redissonClient;

    /**
     * 获取运行时任务
     *
     * @param businessId 业务ID
     * @return 运行时任务信息
     */
    @GetMapping("/runtime-tasks")
    public ResponseData getRuntimeTasks(@RequestParam("businessId") String businessId, @RequestParam("taskId") String taskId) {
        try {
            DKRuntimeTask runtimeTaskList = runtimeTaskRepository.findByIdAndStatus(taskId, TaskStatus.PENDING);
            return ResponseData.ok(runtimeTaskList);
        }
        catch (Exception e) {
            log.error("获取运行时任务失败: {}", businessId, e);
            throw new BusinessException("获取运行时任务失败");
        }
    }

    /**
     * 获取审计跟踪记录
     *
     * @param businessId 业务ID
     * @return 审计跟踪信息
     */
    @GetMapping("/getAnAuditTrail")
    public ResponseData getAnAuditTrail(@RequestParam String businessId) {
        try {
            // 获取运行时任务
            List<DKRuntimeTask> runtimeTasks = runtimeTaskRepository.findByBusinessId(businessId);
            return ResponseData.ok(runtimeTasks);
        }
        catch (Exception e) {
            log.error("获取审计跟踪失败: {}", businessId, e);
            throw new BusinessException("获取审计跟踪失败");
        }
    }

    /**
     * 处理任务
     *
     * @param processDataDto 任务处理数据
     * @return 处理后的任务信息
     */
    @PostMapping("/runtime-tasks/process")
    @DistributedLock(key = "'workflow_task_lock_' + #processDataDto.id", expire = 5, errorMsg = "请刷新列表再试")
    public ResponseData processTasks(@RequestBody ProcessDataDto processDataDto) {
        DKRuntimeTask currentTask = runtimeTaskRepository.findByIdAndStatus(processDataDto.getId(), TaskStatus.PENDING);
        if (currentTask == null) {
            throw new BusinessException("未找到业务ID为 " + processDataDto.getId() + " 的待办理任务记录,请刷新列表");
        }
        activityService.updateCurrentTaskActivity(processDataDto);
        return ResponseData.ok();
    }

    /**
     * 获取任务可用操作列表
     *
     * @param taskId 任务ID
     * @return 可用操作列表, 包含操作值和显示名称
     */
    @GetMapping("/task/operations")
    public ResponseData getTaskOperations(@RequestParam("taskId") String taskId) {
        // 查找任务
        DKRuntimeTask runtimeTask = runtimeTaskRepository.findById(taskId).orElseThrow(() -> new BusinessException("任务不存在，任务ID: " + taskId));

        // 获取活动操作列表
        DKActivity activity = runtimeTask.getActivity();
        List<NodeData.Operation> operations = activity.getOperations();
        if (operations == null || operations.isEmpty()) {
            return ResponseData.ok(Collections.emptyList());
        }

        // 转换操作列表为前端所需格式
        List<Map<String, String>> operationList = operations.stream()
                .map(operation -> Map.of(
                        "value", operation.getType(),
                        "label", operation.getName()
                ))
                .collect(Collectors.toList());
        return ResponseData.ok(operationList);

    }

    /**
     * 查询用户的待办任务
     *
     * @param userId 用户ID
     * @param deptId 部门ID
     * @return 待办任务列表
     */
    @GetMapping("/tasks/todo")
    public ResponseData getTodoTasks(@RequestParam(required = false) String userId, @RequestParam(required = false) String deptId) {
        validateUserOrDeptId(userId, deptId);
        return ResponseData.ok(taskService.getTodoTasks(userId, deptId));
    }

    /**
     * 查询用户的所有相关任务
     *
     * @param userId 用户ID
     * @param deptId 部门ID
     * @return 所有相关任务列表
     */
    @GetMapping("/tasks/all")
    public ResponseData getAllTasks(@RequestParam(required = false) String userId, @RequestParam(required = false) String deptId) {
        validateUserOrDeptId(userId, deptId);
        return ResponseData.ok(taskService.getAllTasks(userId, deptId));
    }

    /**
     * 获取流程当前活动页面信息
     *
     * @return 当前活动页面路径
     */
    @GetMapping("/process/page")
    public ResponseData processPagePath(@RequestParam("taskId") String taskId) {
        DKRuntimeTask runtimeTask = runtimeTaskRepository.findByIdAndStatus(taskId, TaskStatus.PENDING);
        return ResponseData.ok(runtimeTask.getActivity().getPageUrl());
    }

    /**
     * 获取流程当前活动详细信息
     *
     * @return 当前活动信息, 包含操作列表和状态
     */
    @GetMapping("/activity-info")
    public ResponseData getActivityInfo(@RequestParam("taskId") String taskId) {
        DKRuntimeTask currentTask = runtimeTaskRepository.findByIdAndStatus(taskId, TaskStatus.PENDING);

        DKActivity activity = currentTask.getActivity();
        List<NodeData.Operation> operations = activity.getOperations();
        List<Map<String, String>> operationList = operations.stream()
                .map(operation -> Map.of(
                        "value", operation.getType(),
                        "label", operation.getName()
                )).toList();

        return ResponseData.ok(Map.of(
                "operations", operationList,
                "status", currentTask.getStatus()
        ));
    }

    /**
     * 获取任务的下一步可选节点
     *
     * @param taskId 任务ID
     * @return 下一步节点列表
     */
    @GetMapping("/task/next-nodes")
    public ResponseData getNextNodes(@RequestParam("taskId") String taskId) {
        DKRuntimeTask runtimeTask = runtimeTaskRepository.findById(taskId).orElseThrow(() -> new BusinessException("任务不存在，任务ID: " + taskId));

        List<Map<String, Object>> nextNodes = activityService.getNextActivities(runtimeTask.getActivity(), runtimeTask.getBusinessId())
                .stream().filter(activity -> activity.getType() != ActivityType.gateway && activity.getType() != ActivityType.start && activity.getType() != ActivityType.end)
                .map(activity -> {
                    Map<String, Object> node = new HashMap<>();
                    node.put("id", activity.getId());
                    node.put("name", activity.getName());
                    node.put("code", activity.getCode());
                    return node;
                })
                .collect(Collectors.toList());

        return ResponseData.ok(nextNodes);
    }

    /**
     * 获取节点的处理人和部门信息
     *
     * @param nodeId 节点ID
     * @return 节点信息，包含处理人和部门列表
     */
    @GetMapping("/node/info")
    public ResponseData getNodeInfo(@RequestParam("nodeId") String nodeId) {
        DKActivity activity = activityRepository.findById(nodeId).orElseThrow(() -> new BusinessException("节点不存在，节点ID: " + nodeId));

        // 获取处理人列表
        List<User> approvers = new ArrayList<>();
        if (!CollectionUtils.isEmpty(activity.getApprovers())) {
            approvers = userInfoHolder.getUserListByUserIds(activity.getApprovers());
        }

        // 获取部门列表
        List<Map<String, Object>> departments = new ArrayList<>();
        if (!CollectionUtils.isEmpty(activity.getDepartments())) {
            departments = activity.getDepartments().stream()
                    .map(deptId -> {
                        Map<String, Object> dept = new HashMap<>();
                        dept.put("deptId", deptId);
                        // 这里需要调用系统的部门服务获取部门名称
                        dept.put("deptName", "部门" + deptId); // 示例代码，实际需要替换
                        return dept;
                    })
                    .collect(Collectors.toList());
        }

        Map<String, Object> result = new HashMap<>();
        result.put("approvers", approvers);
        result.put("departments", departments);
        result.put("defaultApprovers", activity.getApprovers());
        result.put("defaultDepartments", activity.getDepartments());

        return ResponseData.ok(result);
    }

    /**
     * 验证用户ID或部门ID是否存在
     */
    private void validateUserOrDeptId(String userId, String deptId) {
        if (StringUtils.isBlank(userId) && StringUtils.isBlank(deptId)) {
            throw new BusinessException("用户ID和部门ID不能同时为空");
        }
    }

    /**
     * 为任务列表补充用户信息
     */
    private void enrichTasksWithUserInfo(List<DKRuntimeTask> tasks) {
        if (CollectionUtils.isEmpty(tasks)) {
            return;
        }
        List<String> userIds = tasks.stream()
                .map(DKRuntimeTask::getProcessorId)
                .collect(Collectors.toList());
        List<User> users = userInfoHolder.getUserListByUserIds(userIds);

        tasks.forEach(task -> users.stream()
                .filter(user -> user.getUserId().equals(task.getProcessorId()))
                .findFirst()
                .ifPresent(user -> task.setProcessorName(user.getNickName())));
    }
} 